
#include "lyj_dokan.h"
#include "lyj_ebackup.h"
#include "lyj_filenode.h"
#include <locale.h>

static lyj_ebackup_t m_ebackup;

static lyj_ebackup_t *lyj_ebackup_init(LPCWSTR file_path, LPCWSTR mount_point)
{
    lyj_ebackup_t *ebackup = &m_ebackup;
	lyj_type_memzero(ebackup);
    wcsncpy_s(ebackup->file_path, LYJ_DOKAN_MAX_PATH, file_path, wcslen(file_path));
    wcsncpy_s(ebackup->mount_point, LYJ_DOKAN_MAX_PATH, mount_point, wcslen(mount_point));
    lyj_wlog(L"file_path %ls", ebackup->file_path);
    lyj_wlog(L"mount_point %ls", ebackup->mount_point);
    lyj_wlog(L"version: %u %u", DokanVersion(), DokanDriverVersion());
    ebackup->dokan_options.Version = DOKAN_VERSION;
    ebackup->dokan_options.MountPoint = ebackup->mount_point;
    ebackup->dokan_options.Options |= DOKAN_OPTION_ALT_STREAM;
    ebackup->dokan_options.GlobalContext = (ULONG64)ebackup;
#ifdef _DEBUG
    ebackup->dokan_options.Options |= DOKAN_OPTION_DEBUG;
#endif
#ifdef LYJ_LOG
    ebackup->dokan_options.Options |= DOKAN_OPTION_STDERR;
#endif
    
    lyj_dokan_init_operations(&ebackup->dokan_operations);
    ebackup->kv_store = lyj_kv_store_init(ebackup->file_path);

    if (LYJ_RET_OK != lyj_filenode_init_root(ebackup->kv_store))
    {
        exit(3);
    }
	return ebackup;
}

static void lyj_ebackup_destroy(lyj_ebackup_t* ebackup)
{
    if (!ebackup) return;
    lyj_kv_store_destroy(ebackup->kv_store);
}

static BOOL WINAPI lyj_ctrl_handler(DWORD dwCtrlType) {
    switch (dwCtrlType) {
    case CTRL_C_EVENT:
    case CTRL_BREAK_EVENT:
    case CTRL_CLOSE_EVENT:
    case CTRL_LOGOFF_EVENT:
    case CTRL_SHUTDOWN_EVENT:
        SetConsoleCtrlHandler(lyj_ctrl_handler, FALSE);
        DokanRemoveMountPoint(m_ebackup.mount_point);
        return TRUE;
    default:
        return FALSE;
    }
}
static void lyj_ebackup_run(lyj_ebackup_t* ebackup)
{
    int status;

    if (!SetConsoleCtrlHandler(lyj_ctrl_handler, TRUE)) {
        lyj_real_wlog(L"Control Handler is not set.");
    }
    DokanInit();
    status = DokanMain(&ebackup->dokan_options, &ebackup->dokan_operations);
    DokanShutdown();
    switch (status) {
    case DOKAN_SUCCESS:
        lyj_real_wlog(L"Success");
        break;
    case DOKAN_ERROR:
        lyj_real_wlog(L"Error");
        break;
    case DOKAN_DRIVE_LETTER_ERROR:
        lyj_real_wlog(L"Bad Drive letter");
        break;
    case DOKAN_DRIVER_INSTALL_ERROR:
        lyj_real_wlog(L"Can't install driver");
        break;
    case DOKAN_START_ERROR:
        lyj_real_wlog(L"Driver something wrong");
        break;
    case DOKAN_MOUNT_ERROR:
        lyj_real_wlog(L"Can't assign a drive letter");
        break;
    case DOKAN_MOUNT_POINT_ERROR:
        lyj_real_wlog(L"Mount point error");
        break;
    case DOKAN_VERSION_ERROR:
        lyj_real_wlog(L"Version error");
        break;
    default:
        lyj_real_wlog(L"Unknown error: %d", status);
        break;
    }
}
int __cdecl wmain(ULONG argc, PWCHAR argv[]) {

    lyj_ebackup_t* ebackup;
    setlocale(LC_ALL, "");
    if (argc != 3)
    {
        wprintf(L"%ls file_path mount_point\n", argv[0]);
        return -1;
    }
    ebackup = lyj_ebackup_init(argv[1], argv[2]);
    lyj_ebackup_run(ebackup);
    return 0;
}